package com.haiyou.common.util.random;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;

import org.apache.commons.lang3.ObjectUtils;

public class RandomUtil {
	private static Random random = new Random();

	/**
	 * 随机指定的key值
	 * 
	 * @param map key 主键 value 概率
	 * @return
	 */
	public static int random(Map<Integer, Integer> map) {
		if (ObjectUtils.isEmpty(map)) {
			return 0;
		}

		int totalRate = 0;
		for (int v : map.values()) {
			totalRate = totalRate + v;
		}
		if (totalRate <= 0) {
			return 0;
		}
		
		int random = random(totalRate);
		
		for (Entry<Integer, Integer> entry : map.entrySet()) {
			int rate = entry.getValue();
			if (random < rate) {
				return entry.getKey();
			}
			random -= rate;
		}
		
		return 0;
	}
	
	public static int random(int max){
		if(max <= 1){
			return 0;
		}
		return random.nextInt(max);
	}
	
	/**
	 * 随机区间
	 * @param min
	 * @param max
	 * @param distanceLimit 区间差值限制(差值小于此值返回最小值)
	 * @return
	 */
	public static int randomByNum(int min, int max, int distanceLimit){
		if(min > max){
			max = min;
		}
		int distance = max - min;
		if (distance < distanceLimit){
			return min;
		}
		return min + random.nextInt(distance + 1);
	}
	
	
	public static List<Integer> randomMultiNumber(Collection<Integer> list1,Collection<Integer> list2, int count,
			boolean unique) {
		List<Integer> orginList = new ArrayList<>(list1);
		orginList.removeAll(list2);
		if(orginList.isEmpty()){
			return new ArrayList<>();
		}
		if(orginList.size() <= count){
			return orginList;
		}
		Collections.shuffle(orginList);
		List<Integer> list = new ArrayList<>();
		for (int i = 0; i < count; i++) {
			list.add(orginList.get(i));
		}
		return list;
	}
	
	public static List<Integer> randomMultiNumber(int min,int max,Collection<Integer> list2, int count,
			boolean unique) {
		try {
			List<Integer> orginList = new ArrayList<>();
			for (int i = min; i <= max; i++) {
				orginList.add(i);
			}
			return randomMultiNumber(orginList, list2, count, unique);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
	}
	
	/**
	 * 在min和max之间随机count个数
	 * @param min 最小数值
	 * @param max 最大数值
	 * @param unique 随机的数是否唯一
	 * @param excludeList 排除数集合
	 * @return List<Integer>
	 * 
	 */
	public static List<Integer> randomMultiNumber(int min, int max, int count,
			boolean unique, Collection<Integer> excludeList) {
		List<Integer> list = new ArrayList<Integer>(count);
		int distance = max - min;
		if(count <= 0 || distance < 0){
			return list;
		}else if(unique && (distance + 1) <= count){
			for (int i = min; i <= max; i++) {
				list.add(i);
			}
			return list;
		}
		int value = min;
		Set<Integer> has = new HashSet<>();
		while (count > 0) {
			if (distance > 1) {
				value = min + random.nextInt(distance + 1);
			}else{
				value = min;
			}
			if ((unique && list.contains(value)) //随机值不重复
					|| (excludeList != null && excludeList.contains(value))) { //随机值过滤
				if(!has.contains(value)){
					has.add(value);
					if(has.size() >= distance){
						break;
					}
				}
				continue;
			}
			list.add(value);
			--count;
		}
		return list;
	}
	
	  /**
     * 随机从List中取出一项
     * 
     * @param objs
     * @return
     */
    public static final <T> T rand(List<T> objs) {
        int size = objs.size();
        if (size < 1)
            return null;
        else if (size == 1)
            return objs.get(0);

        int v = random.nextInt(size);
        return objs.get(v);
    }
    
    /**
     * 随机获得列表中的元素
     *
     * @param <T>  元素类型
     * @param list 列表
     * @return 随机元素
     */
    public static <T> T randomEle(List<T> list) {
        return randomEle(list, list.size());
    }

    /**
     * 随机获得列表中的元素
     *
     * @param <T>   元素类型
     * @param list  列表
     * @param limit 限制列表的前N项
     * @return 随机元素
     */
    public static <T> T randomEle(List<T> list, int limit) {
        return list.get(randomInt(limit));
    }

    /**
     * 随机获得数组中的元素
     *
     * @param <T>   元素类型
     * @param array 列表
     * @return 随机元素
     */
    public static <T> T randomEle(T[] array) {
        return randomEle(array, array.length);
    }

    /**
     * 随机获得数组中的元素
     *
     * @param <T>   元素类型
     * @param array 列表
     * @param limit 限制列表的前N项
     * @return 随机元素
     */
    public static <T> T randomEle(T[] array, int limit) {
        return array[randomInt(limit)];
    }

    /**
     * 随机获得列表中的一定量元素
     *
     * @param <T>   元素类型
     * @param list  列表
     * @param count 随机取出的个数
     * @return 随机元素
     */
    public static <T> List<T> randomEles(List<T> list, int count) {
        final List<T> result = new ArrayList<T>(count);
        int limit = list.size();
        while (result.size() < count) {
            result.add(randomEle(list, limit));
        }

        return result;
    }

    /**
     * 随机获得列表中的一定量的不重复元素，返回Set
     *
     * @param <T>        元素类型
     * @param collection 列表
     * @param count      随机取出的个数
     * @return 随机元素
     * @throws IllegalArgumentException 需要的长度大于给定集合非重复总数
     */
    public static <T> Set<T> randomEleSet(Collection<T> collection, int count) {
        ArrayList<T> source = new ArrayList<>(new HashSet<>(collection));
        if (count > source.size()) {
//            throw new IllegalArgumentException("Count is larger than collection distinct size !");
        	return new HashSet<>(collection);
        }

        final HashSet<T> result = new HashSet<T>(count);
        int limit = collection.size();
        while (result.size() < count) {
            result.add(randomEle(source, limit));
        }

        return result;
    }
    
    /**
     * 获得指定范围内的随机数 [0,limit)
     *
     * @param limit 限制随机数的范围，不包括这个数
     * @return 随机数
     */
    public static int randomInt(int limit) {
        return random.nextInt(limit);
    }

	public static int randomInt(int min,int max){
		return random.nextInt(max - min + 1) + min;
	}
	
}
